﻿//
// Copyright (c) 2010
// by Chris Paterra
//
// Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated 
// documentation files (the "Software"), to deal in the Software without restriction, including without limitation 
// the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and 
// to permit persons to whom the Software is furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in all copies or substantial portions 
// of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED 
// TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 
// THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF 
// CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER 
// DEALINGS IN THE SOFTWARE.
//

using System.ComponentModel;
using System.Web.UI.WebControls;
using System.Web.UI;
using System;
using DotNetNuke.ContentLibrary.Components.Common;
using DotNetNuke.ContentLibrary.Components.Controllers;
using DotNetNuke.ContentLibrary.Components.Data;
using Telerik.Web.UI;

namespace DotNetNuke.ContentLibrary.Components.WebControls 
{

	/// <summary>
	/// A simple data grid (DnnGrid, which is our Telerik implementation) that can be placed in a simple stand-alone module to display all site favorites or it can be used within a module and filtered by Content Type.
	/// </summary>
	[DefaultProperty("Width"), Themeable(false)]
	[ToolboxData("<{0}:FavoritesList runat=server> </{0}:FavoritesList>")]
	public class FavoritesList : ControlBase
	{

		#region Private Members

		protected IContentLibraryController Controller { get; private set; }
		private DotNetNuke.Web.UI.WebControls.DnnGrid _favoritesGrid;

		/// <summary>
		/// Used within the control to manage the current page index of the grid.
		/// </summary>
		private int PageIndex {
			get {
				var pageIndex = 0;
				if (ViewState["PageIndex"] != null) {
					pageIndex = Convert.ToInt32(ViewState["PageIndex"]);
				}
				return pageIndex;
			}
			set { ViewState["PageIndex"] = value; }
		}

		#endregion

		#region Constructors

		/// <summary>
		/// 
		/// </summary>
		public FavoritesList()
			: this(new ContentLibraryController(new SqlDataProvider()))
		{
		}

		/// <summary>
		/// 
		/// </summary>
		/// <param name="controller"></param>
		public FavoritesList(IContentLibraryController controller)
		{
			if (controller == null)
			{
				throw new ArgumentException(@"Controller is nothing.", "controller");
			}

			Controller = controller;
		}

		#endregion

		#region Public Properties

		/// <summary>
		/// When set, this will filter the results based on the content type. If you intend to show all favorites across the site do not set this.
		/// </summary>
		/// <example>Page is a content type that has an ID of 1 in almost every install and when applied would only show favorite pages in the list.</example>
		/// <remarks>Required</remarks>
		[Browsable(false)]
		public int ContentTypeID
		{
			get { return ViewState["ContentTypeID"] != null ? (int)ViewState["ContentTypeID"] : 0; }
			set { ViewState["ContentTypeID"] = value; }
		}

		[Bindable(true), Browsable(true), Category("Appearance"), DefaultValue("Bottom"),
		 Description("Where the pageer should be displayed in relation to the favorite list."), Localizable(false)]
		public ControlBehavior.PagerPlacementMode PagerPlacement
		{
			get { return ViewState["PagerPlacement"] != null ? (ControlBehavior.PagerPlacementMode)ViewState["PagerPlacement"] : ControlBehavior.PagerPlacementMode.Bottom; }
			set { ViewState["PagerPlacement"] = value; }
		}

		/// <summary>
		/// 
		/// </summary>
		/// <remarks></remarks>
		[Bindable(true), Browsable(false), Category("Appearance"), DefaultValue("NumericPages"),
		Description("The way the pager will be displayed."), Localizable(false)]
		private ControlBehavior.PagerStyleMode PagerStyleMode {
			get { return ViewState["PagerStyleMode"] != null ? (ControlBehavior.PagerStyleMode)ViewState["PagerStyleMode"] : ControlBehavior.PagerStyleMode.NumericPages; }
			//set { ViewState["PagerStyleMode"] = value; }
		}

		/// <summary>
		/// The number of items to display at once in the data grid.
		/// </summary>
		[Bindable(true), Browsable(true), Category("Appearance"), DefaultValue("20"),
		 Description("The number of items to display at once in the data grid."), Localizable(false)]
		public int PageSize {
			get { return ViewState["PageSize"] != null ? (int)ViewState["PageSize"] : 20; }
			set { ViewState["PageSize"] = value; }
		}

		#endregion

		#region Public Methods

		/// <summary>
		/// This method will reset the pageindex to 0 and force the grid to retrieve data again using the Rebind method of the grid. 
		/// </summary>
		public void Reset() {
			PageIndex = 0;
			_favoritesGrid.Rebind();
		}

		#endregion

		#region Event Handlers

		/// <summary>
		/// We override this part of the life cycle so we can localized the grid.
		/// </summary>
		/// <param name="e"></param>
		protected override void OnInit(EventArgs e) {
			base.OnInit(e);
			BuildGrid();
		}

		/// <summary>
		/// Adds the necessary control(s) to the controls collection.
		/// </summary>
		protected override void CreateChildControls() 
		{
			base.CreateChildControls();
			Controls.Clear();

			Controls.Add(_favoritesGrid);
		}

		/// <summary>
		/// Creates the user interface.
		/// </summary>
		/// <param name="writer"></param>
		/// <remarks>We are currently rebinding here, in case grid is on same page as the favorite button.</remarks>
		protected override void Render(HtmlTextWriter writer)
		{
			_favoritesGrid.RenderControl(writer);
		}

		/// <summary>
		/// Populates the grid with data, when necessary.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void NeedDataSource(object sender, GridNeedDataSourceEventArgs e) {
			var colFavorites = Controller.GetUserFavoritesByContentType(CurrentUserID, PortalID, ContentTypeID, PageSize, PageIndex);

			//// we may want to incorporate this later for admin/moderators/diff team levels
			//_favoritesGrid.MasterTableView.GetColumn("EditItem").Display = false;
			_favoritesGrid.DataSource = colFavorites;
			_favoritesGrid.VirtualItemCount = colFavorites.Count > 0 ? colFavorites[0].TotalRecords : 0;
		}

		/// <summary>
		/// Formats the data displayed in the grid.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void ItemDataBound(object sender, GridItemEventArgs e) {
			if (e.Item is GridHeaderItem)
			{
				var header = (GridHeaderItem)e.Item;
				header["Title"].Text = Services.Localization.Localization.GetString("SiteFavorites.Header", SharedResourceFile);
			}

			if (!(e.Item is GridDataItem)) return;
			var favoriteKeyID = (int)e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["FavoriteID"];
			var tabID = (int)e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["TabID"];
			var contentKey = (string)e.Item.OwnerTableView.DataKeyValues[e.Item.ItemIndex]["ContentKey"];
			var dataItem = (GridDataItem)e.Item;

			var hlName = ((HyperLink)(dataItem)["Title"].Controls[0]);
			hlName.NavigateUrl = DotNetNuke.Common.Globals.NavigateURL(tabID, "", contentKey);
		}

		/// <summary>
		/// Fires when the user changes the current page in the grid.
		/// </summary>
		/// <param name="sender"></param>
		/// <param name="e"></param>
		protected void PageIndexChanged(object sender, GridPageChangedEventArgs e)
		{
			PageIndex = e.NewPageIndex;
		}

		#endregion

		#region Private Methods

		/// <summary>
		/// Builds the grid user itnerface and assigns events. 
		/// </summary>
		private void BuildGrid()
		{
			_favoritesGrid = new Web.UI.WebControls.DnnGrid
			                 	{
			                 		Width = Width,
			                 		PageSize = PageSize,
			                 		AllowPaging = true,
			                 		AllowCustomPaging = true,
			                 		ID = String.Concat(ID, "_DnnGrid"),
			                 		AutoGenerateColumns = false,
			                 		GroupingEnabled = false,
			                 		ShowGroupPanel = false,
			                 		ShowStatusBar = true, 
			                 	};

			_favoritesGrid.MasterTableView.DataKeyNames = new[] { "FavoriteID", "TabID", "ContentKey" };
			_favoritesGrid.NeedDataSource += NeedDataSource;
			_favoritesGrid.ItemDataBound += ItemDataBound;
			//_favoritesGrid.ItemCommand += ItemCommand;
			_favoritesGrid.PageIndexChanged += PageIndexChanged;

			SetPagerProps();

		    var hyperLinkColumn = new DotNetNuke.Web.UI.WebControls.DnnGridHyperLinkColumn()
			                      	{
			                      		DataTextField = "Title",
			                      		UniqueName = "Title"
			                      	};
			_favoritesGrid.MasterTableView.Columns.Add(hyperLinkColumn); // NeedDataSource will fire immediately after this line. 
		}

		private void SetPagerProps()
		{
			switch (PagerStyleMode) {
				case ControlBehavior.PagerStyleMode.NextPrevAndNumeric:
					_favoritesGrid.PagerStyle.Mode = GridPagerMode.NextPrevAndNumeric;
					break;
				case ControlBehavior.PagerStyleMode.NextPrev:
					_favoritesGrid.PagerStyle.Mode = GridPagerMode.NextPrev;
					break;
				case ControlBehavior.PagerStyleMode.Slider:
					_favoritesGrid.PagerStyle.Mode = GridPagerMode.Slider;
					break;
				default:
					_favoritesGrid.PagerStyle.Mode = GridPagerMode.NumericPages;
					break;
			}

			switch (PagerPlacement) {
				case ControlBehavior.PagerPlacementMode.TopAndBottom:
					_favoritesGrid.PagerStyle.Position = GridPagerPosition.TopAndBottom;
					break;
				case ControlBehavior.PagerPlacementMode.Top:
					_favoritesGrid.PagerStyle.Position = GridPagerPosition.Top;
					break;
				default:
					_favoritesGrid.PagerStyle.Position = GridPagerPosition.Bottom;
					break;
			}
		}

		#endregion

	}
}